package ru.ifmo.croak.impl.stress.query.team1;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.ifmo.croak.api.QueryService;
import ru.ifmo.croak.util.CroakFactory;

/**
 * @author Roman Kolganov
 *         23.05.11
 */
public class QueryStressMain implements Runnable {

    private static final Logger log = LoggerFactory.getLogger(QueryStressMain.class);
    private static final int POOL_SIZE = 10;
    private static final long DELAY = 5000;

    private final Thread[] pool = new Thread[POOL_SIZE];
    private final QueryRequester[] requesters = new QueryRequester[POOL_SIZE];

    public static void main(String[] args) {
        new QueryStressMain("stress.query").run();
    }

    private final String name;

    public QueryStressMain(String name) {
        this.name = name;
    }

    public void run() {
        String queryProviderName = CroakFactory.getInstance().getProperty(name + ".provider");
        QueryService query = CroakFactory.getInstance().getImplementation(QueryService.class, queryProviderName);
        for (int i = 0; i < POOL_SIZE; i++) {
            requesters[i] = new QueryRequester(query);
            pool[i] = new Thread(requesters[i]);
            pool[i].start();
        }
        long initialTime = System.currentTimeMillis();
        long sent = 0;
        long queryReceived = 0;
        long symbolsReceived = 0;
        long aborted = 0;
        long sleepTime = DELAY;
        while (!Thread.interrupted()) {
            try {
                Thread.sleep(sleepTime);
            } catch (InterruptedException e) {
                break;
            }
            long currentTime = System.currentTimeMillis();
            long lastSent = 0;
            long lastQueryReceived = 0;
            long lastSymbolsReceived = 0;
            long lastAborted = 0;
            for (QueryRequester requester : requesters) {
                lastSent += requester.sent();
                lastQueryReceived += requester.queryReceived();
                lastSymbolsReceived += requester.symbolsReceived();
                lastAborted += requester.aborted();
            }
            log.info("For the last " + (DELAY / 1000) + " sec sent "
                    + (lastSent - sent) + " requests, aborted "
                    + (lastAborted - aborted) + " requests,\n received "
                    + (lastQueryReceived - queryReceived)
                    + " queries and " + (lastSymbolsReceived - symbolsReceived)
                    + " symbols.\n Totally (for the "
                    + ((System.currentTimeMillis() - initialTime) / 1000)
                    + " sec) sent " + lastSent + " requests, aborted "
                    + lastAborted + " requests,\n received "
                    + lastQueryReceived + " queries and "
                    + lastSymbolsReceived + " symbols.");
            sent = lastSent;
            queryReceived = lastQueryReceived;
            symbolsReceived = lastSymbolsReceived;
            aborted = lastAborted;
            sleepTime = DELAY - (System.currentTimeMillis() - currentTime);
            if (sleepTime < 0) {
                sleepTime = 0;
            }
        }
        shutdown();
    }

    public void shutdown() {
        for (Thread t : pool) {
            t.interrupt();
        }
    }

}
